home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 4 / The Arsenal Files 4 (Arsenal Computer).ISO / ham / sattrk31.tgz / sattrack-3.1.tar / SatTrack / src / sattrack / satgraph.c < prev    next >
C/C++ Source or Header  |  1995-03-16  |  57KB  |  1,704 lines

  1. /******************************************************************************/
  2. /*                                                                            */
  3. /*  Title       : satgraph.c                                                  */
  4. /*  Author      : Manfred Bester                                              */
  5. /*  Date        : 13Dec94                                                     */
  6. /*  Last change : 15Mar95                                                     */
  7. /*                                                                            */
  8. /*  Synopsis    : SatTrack graphics display routines.                         */
  9. /*                                                                            */
  10. /*                                                                            */
  11. /*  SatTrack is Copyright (c) 1992, 1993, 1994, 1995 by Manfred Bester.       */
  12. /*  All Rights Reserved.                                                      */
  13. /*                                                                            */
  14. /*  Permission to use, copy, and distribute SatTrack and its documentation    */
  15. /*  in its entirety for educational, research and non-profit purposes,        */
  16. /*  without fee, and without a written agreement is hereby granted, provided  */
  17. /*  that the above copyright notice and the following three paragraphs appear */
  18. /*  in all copies. SatTrack may be modified for personal purposes, but        */
  19. /*  modified versions may NOT be distributed without prior consent of the     */
  20. /*  author.                                                                   */
  21. /*                                                                            */
  22. /*  Permission to incorporate this software into commercial products may be   */
  23. /*  obtained from the author, Dr. Manfred Bester, 1636 M. L. King Jr. Way,    */
  24. /*  Berkeley, CA 94709, USA. Note that distributing SatTrack 'bundled' in     */
  25. /*  with ANY product is considered to be a 'commercial purpose'.              */
  26. /*                                                                            */
  27. /*  IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, */
  28. /*  SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF   */
  29. /*  THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR HAS BEEN ADVISED  */
  30. /*  OF THE POSSIBILITY OF SUCH DAMAGE.                                        */
  31. /*                                                                            */
  32. /*  THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT      */
  33. /*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A   */
  34. /*  PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"      */
  35. /*  BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, */
  36. /*  UPDATES, ENHANCEMENTS, OR MODIFICATIONS.                                  */
  37. /*                                                                            */
  38. /******************************************************************************/
  39.  
  40. #ifdef XWINDOW
  41.  
  42. #include <stdio.h>
  43. #include <math.h>
  44. #include <string.h>
  45.  
  46. #include <X11/Intrinsic.h>
  47. #include <X11/Shell.h>
  48. #include <X11/StringDefs.h>
  49. #include <X11/Xlib.h>
  50.  
  51. #include "satglobalsx.h"
  52. #include "sattrack.h"
  53. #include "mir.h"
  54. #include "shuttle.h"
  55. #include "world.xbm"
  56.  
  57. /******************************************************************************/
  58. /*                                                                            */
  59. /* definitions                                                                */
  60. /*                                                                            */
  61. /* the first five parameters are imported from the bitmap file 'world.xbm'    */
  62. /*                                                                            */
  63. /******************************************************************************/
  64.  
  65. #define MAPWIDTH      (unsigned int) world_width              /* [pixels]     */
  66. #define MAPHEIGHT     (unsigned int) world_height             /* [pixels]     */
  67. #define MAPTYPE       (unsigned int) world_type               /* 1 or 2       */
  68. #define MAPWIDTHD     (double) world_widthd                   /* [deg]        */
  69. #define MAPHEIGHTD    (double) world_heightd                  /* [deg]        */
  70.  
  71. #define GRIDSCALEX    ((double) MAPWIDTH  / MAPWIDTHD)        /* [pixels/deg] */
  72. #define GRIDSCALEY    ((double) MAPHEIGHT / MAPHEIGHTD)       /* [pixels/deg] */
  73.  
  74. #define MARGINTOP     (unsigned int) 20                       /* black frame  */
  75. #define MARGINBOT     (unsigned int) 20                       /* around the   */
  76. #define MARGINLFT     (unsigned int) 10                       /* world map    */
  77. #define MARGINRGT     (unsigned int) 10                       /* [pixels]     */
  78.  
  79. #define WINWIDTH      (unsigned int) (MAPWIDTH  + MARGINLFT + MARGINRGT)
  80. #define WINHEIGHT     (unsigned int) (MAPHEIGHT + MARGINTOP + MARGINBOT)
  81. #define HEADERROW     (unsigned int) (MARGINTOP - 5)
  82. #define FOOTERROW     (unsigned int) (MARGINTOP + MAPHEIGHT + 15)
  83.  
  84. /******************************************************************************/
  85. /*                                                                            */
  86. /* X Window stuff and other global definitions                                */
  87. /*                                                                            */
  88. /******************************************************************************/
  89.  
  90. static Display        *theDisplay;
  91. static Window         theWindow;
  92. static GC             theGC;
  93. static Colormap       theColormap;
  94. static XColor         color;
  95. static Drawable       drawable;
  96. static Pixmap         pixmap;
  97. static XSegment       gridZero[2], gridLinesX[NGRIDX*2], gridLinesY[NGRIDY*2];
  98. static XSegment       visibCircleSatPix[NSEGSVC], visibCircleGndPix[NSEGSVC];
  99. static XSegment       visibCircleSunPix[NSEGSVC], groundTrackPix[NSEGSGT];
  100. static XPoint         stsPoints[NSTSPOINTS], mirPoints[NMIRPOINTS];
  101. static Widget         topLevel, frame;
  102. static XtAppContext   appContext;
  103. static XEvent         theEvent;
  104. static XtInputMask    mask, lastMask;
  105. static Boolean        eventFlag;
  106. static Arg            warg[3];
  107.  
  108. static double         gndLtd, gndLng, ctyLtd, ctyLng, objEle, satAzi, satEle, 
  109.                       satLtd, satLng, satHgt, mirLtd, mirLng, mirHgt, tdrsHgt, 
  110.                       sepLtd, sepLng, sepHgt, sunLtd, sunLng, sunHgt, 
  111.                       ltd, lng, hgt, visHgt, dH;
  112.  
  113. static long           selOrbitNum;
  114.  
  115. static unsigned long  foregroundPixel, backgroundPixel, 
  116.                       redPixel, greenPixel, lightGreenPixel, 
  117.                       nightBluePixel, darkBluePixel, oceanBluePixel, 
  118.                       lightBluePixel, veryLightBluePixel, 
  119.                       darkYellowPixel, lightYellowPixel, 
  120.                       blackPixel, darkGreyPixel, mediumGreyPixel, whitePixel; 
  121.  
  122. static unsigned int   w, h;
  123.  
  124. static int            x, y, theScreen, nPoints, initFlag, mapSize, gndSpot, 
  125.                       satSpot, tdrsFlag, mirFlag, metFlag, satFlag, selFlag, 
  126.                       dayFlag, orbFlag, lchFlag, craFlag, nTdrs, nShuttle, 
  127.                       gndLocX, gndLocY, ctyLocX, ctyLocY, satLocX, satLocY, 
  128.                       mirLocX, mirLocY, sunLocX, sunLocY, argC;
  129.  
  130. static int            failFlag = FALSE;
  131.  
  132. char                  idStr[80], str[80], str1[120], str2[120], longStr[120], 
  133.                       appName[80], selName[40], tdrsName[40], *argV[5];
  134.  
  135.  
  136. typedef struct {
  137.     XSegment gndCircle[NSEGSVC];
  138.     } groundType;
  139.  
  140. static groundType gndCircleSave[MAXSTATIONS];
  141.  
  142.  
  143. typedef struct {
  144.     XSegment tdrsCircle[NSEGSVC];
  145.     } tdrsType;
  146.  
  147. static tdrsType tdrsCircleSave[MAXTDRS];
  148.  
  149.  
  150. /******************************************************************************/
  151. /*                                                                            */
  152. /* DrawShuttle: draws space shuttle icon                                      */
  153. /*                                                                            */
  154. /*              orbFlag = FALSE  in orbit                                     */
  155. /*              orbFlag = TRUE   not in orbit                                 */
  156. /*                                                                            */
  157. /******************************************************************************/
  158.  
  159. void DrawShuttle(nStr,selFl,dayFl)
  160.  
  161. int  selFl, dayFl;
  162. char *nStr;
  163.  
  164. {
  165.     int i;
  166.  
  167.     nPoints = sizeof (stsPointsWhite) / sizeof (XPoint);
  168.  
  169.     for (i = 0; i < nPoints; i++)
  170.     {
  171.         if (!orbFlag)                                  /* on-orbit attitude   */
  172.         {
  173.             stsPoints[i].x =  stsPointsWhite[i].x + (short int) satLocX;
  174.             stsPoints[i].y =  stsPointsWhite[i].y + (short int) satLocY;
  175.         }
  176.  
  177.         else                                           /* pre-launch attitude */
  178.         {
  179.             stsPoints[i].x =  stsPointsWhite[i].y + (short int) satLocX;
  180.             stsPoints[i].y = -stsPointsWhite[i].x + (short int) satLocY;
  181.         }
  182.     }
  183.  
  184.     if (orbFlag)
  185.         dayFl = DAY;
  186.  
  187.     if (dayFl == NIGHT)
  188.         XSetForeground(theDisplay,theGC,mediumGreyPixel);
  189.     else
  190.         XSetForeground(theDisplay,theGC,whitePixel);
  191.  
  192.     XDrawPoints(theDisplay,drawable,theGC,stsPoints,nPoints,CoordModeOrigin);
  193.  
  194.     nPoints = sizeof (stsPointsBlack) / sizeof (XPoint);
  195.  
  196.     for (i = 0; i < nPoints; i++)
  197.     {
  198.         if (!orbFlag)                                  /* on-orbit attitude   */
  199.         {
  200.             stsPoints[i].x =  stsPointsBlack[i].x + (short int) satLocX;
  201.             stsPoints[i].y =  stsPointsBlack[i].y + (short int) satLocY;
  202.         }
  203.  
  204.         else                                           /* pre-launch attitude */
  205.         {
  206.             stsPoints[i].x =  stsPointsBlack[i].y + (short int) satLocX;
  207.             stsPoints[i].y = -stsPointsBlack[i].x + (short int) satLocY;
  208.         }
  209.     }
  210.  
  211.     XSetForeground(theDisplay,theGC,blackPixel);
  212.     XDrawPoints(theDisplay,drawable,theGC,stsPoints,nPoints,CoordModeOrigin);
  213.  
  214.     /* show mission number if several shuttles are in the multisat list */
  215.  
  216.     if (nShuttle > 1)
  217.     {
  218.         if (!orbFlag)
  219.             x = ((int) (MARGINLFT + MAPWIDTH) - satLocX > 100) 
  220.                          ? 6 : -12 - ((int) (strlen(nStr)) * 6);
  221.         else
  222.             x = 13;
  223.  
  224.         if (!orbFlag)
  225.             y = ((int) (MARGINTOP + MAPHEIGHT) - satLocY < 25) ? -8 : 20;
  226.         else
  227.             y = -4;
  228.  
  229.         if (selFl)
  230.             XSetForeground(theDisplay,theGC,lightBluePixel);
  231.         else
  232.             XSetForeground(theDisplay,theGC,lightYellowPixel);
  233.  
  234.         XDrawString(theDisplay,drawable,theGC,satLocX+x,satLocY+y,
  235.                     nStr,(int) strlen(nStr));
  236.     }
  237.  
  238.     return;
  239. }
  240.  
  241. /******************************************************************************/
  242. /*                                                                            */
  243. /* DrawMir: draws Mir space station icon                                      */
  244. /*                                                                            */
  245. /******************************************************************************/
  246.  
  247. void DrawMir(dayFl)
  248.  
  249. int dayFl;
  250.  
  251. {
  252.     int i;
  253.  
  254.     nPoints = sizeof (mirPointsWhite) / sizeof (XPoint);
  255.  
  256.     for (i = 0; i < nPoints; i++)
  257.     {
  258.         mirPoints[i].x = mirPointsWhite[i].x + (short int) satLocX;
  259.         mirPoints[i].y = mirPointsWhite[i].y + (short int) satLocY;
  260.     }
  261.  
  262.     if (dayFl == NIGHT)
  263.         XSetForeground(theDisplay,theGC,mediumGreyPixel);
  264.     else
  265.         XSetForeground(theDisplay,theGC,whitePixel);
  266.  
  267.     XDrawPoints(theDisplay,drawable,theGC,mirPoints,nPoints,CoordModeOrigin);
  268.  
  269.     nPoints = sizeof (mirPointsBlack) / sizeof (XPoint);
  270.  
  271.     for (i = 0; i < nPoints; i++)
  272.     {
  273.         mirPoints[i].x = mirPointsBlack[i].x + (short int) satLocX;
  274.         mirPoints[i].y = mirPointsBlack[i].y + (short int) satLocY;
  275.     }
  276.  
  277.     XSetForeground(theDisplay,theGC,blackPixel);
  278.     XDrawPoints(theDisplay,drawable,theGC,mirPoints,nPoints,CoordModeOrigin);
  279.  
  280.     return;
  281. }
  282.  
  283. /******************************************************************************/
  284. /*                                                                            */
  285. /* DrawSat: draws satellite other than Mir or STS                             */
  286. /*                                                                            */
  287. /*          selFl = TRUE    color is blue   (status = SELECT or MARK)         */
  288. /*                = FALSE   color is yellow                                   */
  289. /*                                                                            */
  290. /*          dayFl = NIGHT   color is dark   (blue or yellow)                  */
  291. /*                = ELSE    color is light  (blue or yellow)                  */
  292. /*                                                                            */
  293. /******************************************************************************/
  294.  
  295. void DrawSat(nStr,selFl,dayFl)
  296.  
  297. int  selFl, dayFl;
  298. char *nStr;
  299.  
  300. {
  301.     satSpot = (selFl) ? TRKSPOT : SATSPOT;
  302.  
  303.     if (selFl && dayFl != NIGHT)
  304.         XSetForeground(theDisplay,theGC,lightBluePixel);
  305.  
  306.     if (selFl && dayFl == NIGHT)
  307.         XSetForeground(theDisplay,theGC,darkBluePixel);
  308.  
  309.     if (!selFl && dayFl != NIGHT)
  310.         XSetForeground(theDisplay,theGC,lightYellowPixel);
  311.  
  312.     if (!selFl && dayFl == NIGHT)
  313.         XSetForeground(theDisplay,theGC,darkYellowPixel);
  314.  
  315.     XFillRectangle(theDisplay,drawable,theGC,
  316.                    satLocX - (int) satSpot,satLocY - (int) satSpot,
  317.                    (unsigned int) (satSpot*2+1),(unsigned int) (satSpot*2+1));
  318.  
  319.     x = ((int) (MARGINLFT + MAPWIDTH) - satLocX > 100) 
  320.                  ? 10 : -10 - ((int) (strlen(nStr)) * 6);
  321.  
  322.     y = (satLocY - (int) MARGINTOP < 25) ? 20 : -8;
  323.  
  324.     if (selFl)
  325.         XSetForeground(theDisplay,theGC,lightBluePixel);
  326.     else
  327.         XSetForeground(theDisplay,theGC,lightYellowPixel);
  328.  
  329.     XDrawString(theDisplay,drawable,theGC,satLocX+x,satLocY+y,
  330.                 nStr,(int) strlen(nStr));
  331.  
  332.     return;
  333. }
  334.  
  335. /******************************************************************************/
  336. /*                                                                            */
  337. /* DrawFrame: draws the black frame around world map and the text in the      */
  338. /*            header and footer line                                          */
  339. /*                                                                            */
  340. /******************************************************************************/
  341.  
  342. void DrawFrame()
  343.  
  344. {
  345.     x = 0;
  346.     y = 0;
  347.     w = (unsigned int) (MARGINLFT + MAPWIDTH + MARGINRGT);
  348.     h = (unsigned int) MARGINTOP;
  349.  
  350.     XSetForeground(theDisplay,theGC,blackPixel);
  351.     XFillRectangle(theDisplay,drawable,theGC,x,y,w,h);
  352.  
  353.     if (trackObject == SAT)
  354.     {
  355.         sprintf(str,"%s",selName);
  356.         objEle = satEle;
  357.     }
  358.  
  359.     if (trackObject == SUN)
  360.     {
  361.         sprintf(str,"Sun");
  362.         objEle = sunElevation * CRD;
  363.     }
  364.  
  365.     if (trackObject == MOON)
  366.     {
  367.         sprintf(str,"Moon");
  368.         objEle = moonElevation * CRD;
  369.     }
  370.  
  371.     if (trackingFlag)
  372.     {
  373.         if (objEle > ONEPPM)
  374.             XSetForeground(theDisplay,theGC,lightGreenPixel);
  375.         else
  376.             XSetForeground(theDisplay,theGC,redPixel);
  377.  
  378.         x = 12;
  379.  
  380.         XFillRectangle(theDisplay,drawable,theGC,
  381.                    (int) (MARGINLFT+1),(int) (MARGINTOP-14),
  382.                    (unsigned int) (9),(unsigned int) (9));
  383.     }
  384.  
  385.     XSetForeground(theDisplay,theGC,whitePixel);
  386.     XDrawString(theDisplay,drawable,theGC,(int) (MARGINLFT+2+x),
  387.                 (int) HEADERROW,str,(int) strlen(str));
  388.  
  389.     sprintf(str,"Orbit: %ld",selOrbitNum);
  390.  
  391.     if (mapSize == SMALL)
  392.         XDrawString(theDisplay,drawable,theGC,(int) (MARGINLFT+0.24*MAPWIDTH),
  393.                 (int) HEADERROW,str,(int) strlen(str));
  394.     else
  395.         XDrawString(theDisplay,drawable,theGC,(int) (MARGINLFT+0.18*MAPWIDTH),
  396.                 (int) HEADERROW,str,(int) strlen(str));
  397.  
  398.     if (mapSize == LARGE)
  399.         sprintf(str,"Azi: %5.1f  Ele: %5.1f",satAzi,satEle);
  400.  
  401.     if (mapSize == MEDIUM)
  402.         sprintf(str,"Azi: %3.0f  Ele: %3.0f",satAzi,satEle);
  403.  
  404.     if (mapSize == LARGE || mapSize == MEDIUM)
  405.         XDrawString(theDisplay,drawable,theGC,(int) (MARGINLFT+0.33*MAPWIDTH),
  406.                (int) HEADERROW,str,(int) strlen(str));
  407.  
  408.     if (mapSize == LARGE)
  409.     {
  410.         sprintf(str1,"Lat: %4.1f %s",fabs(satLtd),
  411.                (satLtd >= 0.0) ? "N":"S");
  412.         sprintf(str2,"%s  Lng: %5.1f %s",str1,fabs(satLng),
  413.                (satLng >= 0.0) ? "W":"E");
  414.  
  415.         XDrawString(theDisplay,drawable,theGC,(int) (MARGINLFT+0.53*MAPWIDTH),
  416.                (int) HEADERROW,str2,(int) strlen(str2));
  417.     }
  418.  
  419.     if (mapSize == MEDIUM)
  420.     {
  421.         sprintf(str1,"Lat: %2.0f %s",fabs(satLtd),
  422.                (satLtd >= 0.0) ? "N":"S");
  423.         sprintf(str2,"%s  Lng: %3.0f %s",str1,fabs(satLng),
  424.                (satLng >= 0.0) ? "W":"E");
  425.  
  426.         XDrawString(theDisplay,drawable,theGC,(int) (MARGINLFT+0.54*MAPWIDTH),
  427.                (int) HEADERROW,str2,(int) strlen(str2));
  428.     }
  429.  
  430.     if (mapSize == SMALL)
  431.     {
  432.         sprintf(str1,"Lat: %2.0f %s",fabs(satLtd),
  433.                (satLtd >= 0.0) ? "N":"S");
  434.         sprintf(str2,"%s  Lng: %3.0f %s",str1,fabs(satLng),
  435.                (satLng >= 0.0) ? "W":"E");
  436.  
  437.         XDrawString(theDisplay,drawable,theGC,(int) (MARGINLFT+0.43*MAPWIDTH),
  438.                (int) HEADERROW,str2,(int) strlen(str2));
  439.     }
  440.  
  441.     if (mapSize == LARGE || mapSize == MEDIUM)
  442.     {
  443.         sprintf(str,"%s",xTimeStr);
  444.         XDrawString(theDisplay,drawable,theGC,(int) (MARGINLFT+0.78*MAPWIDTH),
  445.                (int) HEADERROW,str,(int) strlen(str));
  446.     }
  447.  
  448.     if (mapSize == SMALL)
  449.     {
  450.         sprintf(str,"%s",xTimeStr);
  451.         XDrawString(theDisplay,drawable,theGC,(int) (MARGINLFT+0.73*MAPWIDTH),
  452.                (int) HEADERROW,str,(int) strlen(str));
  453.     }
  454.  
  455.     x = 0;
  456.     y = (int) (MARGINTOP + MAPHEIGHT);
  457.     w = (unsigned int) (MARGINLFT + MAPWIDTH + MARGINRGT);
  458.     h = (unsigned int) MARGINBOT;
  459.  
  460.     XSetForeground(theDisplay,theGC,blackPixel);
  461.     XFillRectangle(theDisplay,drawable,theGC,x,y,w,h);
  462.  
  463.     XSetForeground(theDisplay,theGC,whitePixel);
  464.     sprintf(str1,"Ground Track: %s",xGndTrkStr);
  465.  
  466.     if (metFlag && mapSize == SMALL)
  467.     {
  468.         strncpy(longStr,str1,60);
  469.         shortString(str2,longStr,60);
  470.         strcpy(str1,str2);
  471.     }
  472.  
  473.     XDrawString(theDisplay,drawable,theGC,(int) (MARGINLFT+2),
  474.                 (int) FOOTERROW,str1,(int) strlen(str1));
  475.  
  476.     if (metFlag)
  477.     {
  478.         sprintf(str,"%s",xMetStr);
  479.  
  480.         if (mapSize == SMALL)
  481.             XDrawString(theDisplay,drawable,theGC,
  482.                     (int) (MARGINLFT+0.78*MAPWIDTH),
  483.                     (int) FOOTERROW,str,(int) strlen(str));
  484.         else
  485.             XDrawString(theDisplay,drawable,theGC,
  486.                     (int) (MARGINLFT+0.82*MAPWIDTH),
  487.                     (int) FOOTERROW,str,(int) strlen(str));
  488.     }
  489.  
  490.     x = 0;
  491.     y = (int) MARGINTOP;
  492.     w = (unsigned int) MARGINLFT;
  493.     h = (unsigned int) MAPHEIGHT;
  494.  
  495.     XSetForeground(theDisplay,theGC,blackPixel);
  496.     XFillRectangle(theDisplay,drawable,theGC,x,y,w,h);
  497.  
  498.     x = (int) (MARGINLFT + MAPWIDTH);
  499.     y = (int) MARGINTOP;
  500.     w = (unsigned int) MARGINRGT;
  501.     h = (unsigned int) MAPHEIGHT;
  502.  
  503.     XFillRectangle(theDisplay,drawable,theGC,x,y,w,h);
  504.  
  505.     return;
  506. }
  507.  
  508. /******************************************************************************/
  509. /*                                                                            */
  510. /* DrawMap: draws graphics window with world map and other features           */
  511. /*                                                                            */
  512. /******************************************************************************/
  513.  
  514. void DrawMap()
  515.  
  516. {
  517.     int i, nSats;
  518.  
  519.     /* load initial satellite data and check if Mir is in the list */
  520.     /* (the latter is needed for STS-Mir docking maneuvers)        */
  521.     /* also count number of space shuttles in the list             */
  522.  
  523.     mirFlag  = FALSE;
  524.     metFlag  = FALSE;
  525.     nShuttle = 0;
  526.  
  527.     if (liveDispFlag == MULTISAT)
  528.     {
  529.         for (i = 0; i < numSats; i++)
  530.         {
  531.             selFlag = sat[i].statusFl;
  532.             satFlag = sat[i].satTypeFl;
  533.  
  534.             if (selFlag == SELECT)
  535.             {
  536.                 lchFlag = sat[i].launchFl;
  537.                 orbFlag = sat[i].preorbitFl;
  538.                 craFlag = sat[i].crashFl;
  539.  
  540.                 satLtd  = sat[i].satLtd * CRD;;
  541.                 satLng  = sat[i].satLng * CRD;;
  542.                 satHgt  = sat[i].satHgt;
  543.                 satAzi  = sat[i].satAzi * CRD;
  544.                 satEle  = sat[i].satEle * CRD;
  545.                 ctyLtd  = sat[i].ctyLtd;
  546.                 ctyLng  = sat[i].ctyLng;
  547.  
  548.                 tdrsHgt = satHgt;               /* needed for ZOE calculation */
  549.  
  550.                 if (satFlag == STS)
  551.                     selOrbitNum = sat[i].stsOrbNum;
  552.                 else
  553.                     selOrbitNum = sat[i].satOrbNum;
  554.  
  555.                 if (objectNumFlag)
  556.                     sprintf(selName,"%ld",sat[i].satIdNum);
  557.                 else
  558.                     sprintf(selName,"%s",sat[i].satellite);
  559.  
  560.                 if (lchFlag)
  561.                 {
  562.                     strcpy(xMetStr,sat[i].xMetStr);
  563.                     metFlag = (strlen(xMetStr)) ? TRUE : FALSE;
  564.                 }
  565.             }
  566.  
  567.             if (satFlag == MIR)                /* needed for docking maneuver */
  568.             {
  569.                 mirLtd  = sat[i].satLtd * CRD;;
  570.                 mirLng  = sat[i].satLng * CRD;;
  571.                 mirHgt  = sat[i].satHgt;
  572.                 mirFlag = TRUE;
  573.  
  574.                 CalcMapLocation(mirLtd,mirLng,&mirLocX,&mirLocY);
  575.             }
  576.  
  577.             if (satFlag == STS)
  578.                 nShuttle++;
  579.         }
  580.     }
  581.  
  582.     else
  583.     {
  584.         lchFlag = launchFlag;
  585.         orbFlag = preOrbitFlag;
  586.         craFlag = satCrashFlag;
  587.  
  588.         satLtd  = satLat * CRD;
  589.         satLng  = satLong * CRD;
  590.         satHgt  = satHeight;
  591.  
  592.         satAzi = satAzimuth * CRD;
  593.         satEle = satElevation * CRD;
  594.  
  595.         ctyLtd  = cityLat;
  596.         ctyLng  = cityLong;
  597.  
  598.         metFlag = (strlen(xMetStr) && lchFlag) ? TRUE : FALSE;
  599.  
  600.         if (satTypeFlag == STS)
  601.             selOrbitNum = stsOrbitNum;
  602.         else
  603.             selOrbitNum = orbitNum;
  604.  
  605.         sprintf(selName,"%s",satName);
  606.     }
  607.  
  608.     if (craFlag)
  609.     {
  610.         satLtd = ZERO;
  611.         satLng = ZERO;
  612.         satHgt = ZERO;
  613.         satAzi = ZERO;
  614.         satEle = ZERO;
  615.         selOrbitNum = 0L;
  616.         *xGndTrkStr = '\0';
  617.     }
  618.  
  619.     sunLtd = sunLat * CRD;
  620.     sunLng = sunLong * CRD;
  621.     sunHgt = sunDist;
  622.  
  623.     gndLtd = siteLat * CRD;
  624.     gndLng = siteLong * CRD;
  625.  
  626.     if (debugFlag)
  627.     {
  628.         sunLtd = ZERO;
  629.         sunLng = ZERO;
  630.  
  631.         groundStation[0].ltd =  0.0 * CDR;
  632.         groundStation[0].lng = 60.0 * CDR;
  633.         sprintf(groundStation[0].gndStnID,"TEST");
  634.     }
  635.  
  636.     XSetForeground(theDisplay,theGC,foregroundPixel);
  637.     XSetBackground(theDisplay,theGC,backgroundPixel);
  638.  
  639.     /* draw world map */
  640.  
  641.     XCopyPlane(theDisplay,(Drawable) pixmap,(Drawable) drawable,theGC,
  642.                (int) 0,(int) 0,
  643.                (unsigned int) MAPWIDTH,(unsigned int) MAPHEIGHT, 
  644.                (int) MARGINLFT,(int) MARGINTOP,(unsigned long) 1);
  645.  
  646.     /* draw grid */
  647.  
  648.     XSetForeground(theDisplay,theGC,mediumGreyPixel);
  649.     XDrawSegments(theDisplay,drawable,theGC,gridZero,2);
  650.     XSetForeground(theDisplay,theGC,darkGreyPixel);
  651.     XDrawSegments(theDisplay,drawable,theGC,gridLinesX,NGRIDX*2);
  652.     XDrawSegments(theDisplay,drawable,theGC,gridLinesY,NGRIDY*2);
  653.  
  654.     /* draw black frame with header and footer lines */
  655.  
  656.     DrawFrame();
  657.  
  658.     /* draw ground stations and nearest city if satellite is in orbit */
  659.  
  660.     dH = fabs(satHgt - lastSatGraphHeight);
  661.  
  662.     if (!craFlag && !orbFlag)
  663.     {
  664.         /* ground stations */
  665.  
  666.         for (i = 0; i < numGroundStations; i++)
  667.         {
  668.             gndLtd = groundStation[i].ltd * CRD;
  669.             gndLng = groundStation[i].lng * CRD;
  670.  
  671.             if (i == 0)
  672.             {
  673.                 if (strlen(groundStation[0].gndStnID))
  674.                     strcpy(idStr,groundStation[0].gndStnID);
  675.                 else
  676.                     strcpy(idStr,siteName);
  677.             }
  678.  
  679.             else
  680.                 strcpy(idStr,groundStation[i].gndStnID);
  681.  
  682.             gndSpot = (i == 0) ? GNDSPOT : GNDSPOTX;
  683.  
  684.             CalcMapLocation(gndLtd,gndLng,&gndLocX,&gndLocY);
  685.             XSetForeground(theDisplay,theGC,redPixel);
  686.  
  687.             /* recalculate visibility circle of the ground stations only when */
  688.             /* satellite height changes by more than DHLIMIT (1 km)           */
  689.  
  690.             if (dH > DHLIMIT)
  691.             {
  692.                 CalcVisibCircle(&visibCircleGndPix[0],gndLtd,gndLng,satHgt,0.0);
  693.                 SaveGroundSegments(&visibCircleGndPix[0],i);
  694.             }
  695.  
  696.             else
  697.                 LoadGroundSegments(&visibCircleGndPix[0],i);
  698.  
  699.             XDrawSegments(theDisplay,drawable,theGC,visibCircleGndPix,NSEGSVC);
  700.             XFillRectangle(theDisplay,drawable,theGC,
  701.                    gndLocX - (int) gndSpot,gndLocY - (int) gndSpot,
  702.                    (unsigned int) (gndSpot*2+1),(unsigned int) (gndSpot*2+1));
  703.  
  704.             x = ((int) (MARGINLFT + MAPWIDTH) - gndLocX > 100) 
  705.                          ? 10 : -10 - ((int) (strlen(idStr)) * 6);
  706.  
  707.             y = (gndLocY - (int) MARGINTOP < 25) ? 20 : -8;
  708.  
  709.             XSetForeground(theDisplay,theGC,veryLightBluePixel);
  710.             XDrawString(theDisplay,drawable,theGC,gndLocX+x,gndLocY+y,
  711.                         idStr,(int) strlen(idStr));
  712.         }
  713.  
  714.         /* nearest city */
  715.  
  716.         CalcMapLocation(ctyLtd,ctyLng,&ctyLocX,&ctyLocY);
  717.  
  718.         XSetForeground(theDisplay,theGC,redPixel);
  719.         XFillRectangle(theDisplay,drawable,theGC,
  720.                    ctyLocX - (int) CTYSPOT,ctyLocY - (int) CTYSPOT,
  721.                    (unsigned int) (CTYSPOT*2+1),(unsigned int) (CTYSPOT*2+1));
  722.     }
  723.  
  724.     /* recalculate Sun and terminator when they change by half a pixel */
  725.  
  726.     if (curTimeGl - lastSunGraphTime > 0.5 / (double) MAPWIDTH)
  727.     {
  728.         CalcMapLocation(sunLtd,sunLng,&sunLocX,&sunLocY);
  729.         CalcVisibCircle(&visibCircleSunPix[0],sunLtd,sunLng,sunHgt,0.0);
  730.         lastSunGraphTime = curTimeGl;
  731.     }
  732.  
  733.     /* draw Sun and terminator */
  734.  
  735.     XSetForeground(theDisplay,theGC,lightYellowPixel);
  736.     XDrawSegments(theDisplay,drawable,theGC,visibCircleSunPix,NSEGSVC);
  737.     sprintf(str,"*");
  738.     XDrawString(theDisplay,drawable,theGC,sunLocX-2,sunLocY+5,
  739.                 str,(int) strlen(str));
  740.  
  741.     /* draw ground track */
  742.  
  743.     if (!initFlag && !craFlag)
  744.     {
  745.         if (newGndTrkFlag)
  746.         {
  747.             CalcGroundTrack();
  748.             newGndTrkFlag = FALSE;
  749.         }
  750.  
  751.         XSetForeground(theDisplay,theGC,lightBluePixel);
  752.         XDrawSegments(theDisplay,drawable,theGC,groundTrackPix,NSEGSGT);
  753.     }
  754.  
  755.     /* draw all satellites */
  756.  
  757.     nSats = (liveDispFlag == MULTISAT) ? numSats : 1;
  758.     nTdrs = 0;
  759.  
  760.     for (i = 0; i < nSats; i++)
  761.     {
  762.         if (nSats > 1)
  763.         {
  764.             satFlag = sat[i].satTypeFl;
  765.             selFlag = sat[i].statusFl;
  766.             dayFlag = sat[i].eclCode;
  767.             orbFlag = sat[i].preorbitFl;
  768.             craFlag = sat[i].crashFl;
  769.  
  770.             ltd     = sat[i].satLtd * CRD;
  771.             lng     = sat[i].satLng * CRD;
  772.             hgt     = sat[i].satHgt;
  773.  
  774.             if (objectNumFlag)
  775.                 sprintf(str,"%ld",sat[i].satIdNum);
  776.             else
  777.                 sprintf(str,"%s",sat[i].satellite);
  778.  
  779.             sprintf(tdrsName,"%s",sat[i].satellite);
  780.         }
  781.  
  782.         else
  783.         {
  784.             satFlag = satTypeFlag;
  785.             selFlag = SELECT;
  786.             dayFlag = eclipseCode;
  787.             orbFlag = preOrbitFlag;
  788.             craFlag = satCrashFlag;
  789.  
  790.             ltd     = satLat * CRD;
  791.             lng     = satLong * CRD;
  792.             hgt     = satHeight;
  793.             tdrsHgt = 0.0;
  794.  
  795.             sprintf(str,"%s",satName);
  796.         }
  797.  
  798.         /* check if satellite to be drawn is TDRS */
  799.  
  800.         tdrsFlag = (!strncmp(tdrsName,"TDRS",4)) ? TRUE : FALSE;
  801.  
  802.         if ((selFlag && !orbFlag) || (!selFlag && tdrsFlag))
  803.         {
  804.             visHgt = (tdrsFlag) ? tdrsHgt : 0.0;
  805.  
  806.             if (tdrsFlag && nTdrs < MAXTDRS)   /* displayed satellite is TDRS */
  807.             {
  808.                 /* TDRS is selected: show foot print of TDRS on the ground    */
  809.  
  810.                 if (selFlag) 
  811.                 {
  812.                     XSetForeground(theDisplay,theGC,veryLightBluePixel);
  813.                     CalcVisibCircle(&visibCircleSatPix[0],ltd,lng,hgt,0.0);
  814.                 }
  815.  
  816.                 /* TDRS is not selected: show visibility as seen from other   */
  817.                 /* selected satellite                                         */
  818.  
  819.                 else
  820.                 {
  821.                     XSetForeground(theDisplay,theGC,mediumGreyPixel);
  822.  
  823.                     if (dH > DHLIMIT)
  824.                     {
  825.                         CalcVisibCircle(&visibCircleSatPix[0],
  826.                                         ltd,lng,hgt,visHgt);
  827.                         SaveTdrsSegments(&visibCircleSatPix[0],nTdrs);
  828.                     }
  829.  
  830.                     else
  831.                         LoadTdrsSegments(&visibCircleSatPix[0],nTdrs);
  832.                 }
  833.  
  834.                 nTdrs++;
  835.             }
  836.  
  837.             else /* displayed satellite is not TDRS */
  838.             {
  839.                 XSetForeground(theDisplay,theGC,veryLightBluePixel);
  840.                 CalcVisibCircle(&visibCircleSatPix[0],ltd,lng,hgt,visHgt);
  841.             }
  842.  
  843.             XDrawSegments(theDisplay,drawable,theGC,visibCircleSatPix,NSEGSVC);
  844.         }
  845.  
  846.         if (!craFlag)
  847.         {
  848.             CalcMapLocation(ltd,lng,&satLocX,&satLocY);
  849.  
  850.             if (satFlag == BASIC)
  851.                 DrawSat(str,selFlag,dayFlag);
  852.  
  853.             if (satFlag == MIR)
  854.                 DrawMir(dayFlag);
  855.  
  856.             if (satFlag == STS)
  857.             {
  858.                 if (mirFlag)
  859.                 {
  860.                     sepLng = reduce((lng-mirLng),0.0,360.0);
  861.                     sepLtd = fabs(ltd - mirLtd);
  862.                     sepHgt = fabs(hgt - mirHgt);
  863.  
  864.                     /* if separation of STS and Mir is less than 5 deg and */
  865.                     /* the height difference is less than 5 km:            */
  866.                     /* show Mir and STS docked together                    */
  867.  
  868.                     if ((sepLng < 5.0 || sepLng > 355.0) && sepLtd < 5.0 && 
  869.                          sepHgt < 10.0)
  870.                     {
  871.                         satLocX = mirLocX -  8;
  872.                         satLocY = mirLocY + 16;
  873.                     }
  874.                 }
  875.  
  876.                 DrawShuttle(str,selFlag,dayFlag);
  877.             }
  878.         }
  879.     }
  880.  
  881.     if (dH > DHLIMIT)
  882.         lastSatGraphHeight = satHgt;
  883.  
  884.     XFlush(theDisplay);
  885.  
  886.     initFlag = FALSE;
  887.     return;
  888. }
  889.  
  890. /******************************************************************************/
  891. /*                                                                            */
  892. /* CreateColors: creates all colors needed                                    */
  893. /*                                                                            */
  894. /******************************************************************************/
  895.  
  896. void CreateColors()
  897.  
  898. {
  899.     theColormap = DefaultColormap(theDisplay,theScreen);
  900.     color.flags = DoRed | DoGreen | DoBlue;
  901.  
  902.     color.red   = (unsigned short) 65535;                              /* red */
  903.     color.green = (unsigned short) 20000;
  904.     color.blue  = (unsigned short) 25000;
  905.  
  906.     XAllocColor(theDisplay,theColormap,&color);
  907.     redPixel = color.pixel;
  908.  
  909.     color.red   = (unsigned short) 18000;                            /* green */
  910.     color.green = (unsigned short) 48000;
  911.     color.blue  = (unsigned short)  2000;
  912.  
  913.     XAllocColor(theDisplay,theColormap,&color);
  914.     greenPixel = color.pixel;
  915.  
  916.     color.red   = (unsigned short) 18000;                      /* light green */
  917.     color.green = (unsigned short) 52000;
  918.     color.blue  = (unsigned short)  2000;
  919.  
  920.     XAllocColor(theDisplay,theColormap,&color);
  921.     lightGreenPixel = color.pixel;
  922.  
  923.     color.red   = (unsigned short)  5000;                       /* night blue */
  924.     color.green = (unsigned short)  5000;
  925.     color.blue  = (unsigned short) 35000;
  926.  
  927.     XAllocColor(theDisplay,theColormap,&color);
  928.     nightBluePixel = color.pixel;
  929.  
  930.     color.red   = (unsigned short) 34000;                        /* dark blue */
  931.     color.green = (unsigned short) 34000;
  932.     color.blue  = (unsigned short) 52000;
  933.  
  934.     XAllocColor(theDisplay,theColormap,&color);
  935.     darkBluePixel = color.pixel;
  936.  
  937.     color.red   = (unsigned short) 12500;                       /* ocean blue */
  938.     color.green = (unsigned short)  7500;
  939.     color.blue  = (unsigned short) 50000;
  940.  
  941.     XAllocColor(theDisplay,theColormap,&color);
  942.     oceanBluePixel = color.pixel;
  943.  
  944.     color.red   = (unsigned short) 40000;                       /* light blue */
  945.     color.green = (unsigned short) 60000;
  946.     color.blue  = (unsigned short) 65535;
  947.  
  948.     XAllocColor(theDisplay,theColormap,&color);
  949.     lightBluePixel = color.pixel;
  950.  
  951.     color.red   = (unsigned short) 62000;                  /* very light blue */
  952.     color.green = (unsigned short) 65535;
  953.     color.blue  = (unsigned short) 65535;
  954.  
  955.     XAllocColor(theDisplay,theColormap,&color);
  956.     veryLightBluePixel = color.pixel;
  957.  
  958.     color.red   = (unsigned short) 52000;                      /* dark yellow */
  959.     color.green = (unsigned short) 52000;
  960.     color.blue  = (unsigned short) 34000;
  961.  
  962.     XAllocColor(theDisplay,theColormap,&color);
  963.     darkYellowPixel = color.pixel;
  964.  
  965.     color.red   = (unsigned short) 65535;                     /* light yellow */
  966.     color.green = (unsigned short) 65535;
  967.     color.blue  = (unsigned short) 35000;
  968.  
  969.     XAllocColor(theDisplay,theColormap,&color);
  970.     lightYellowPixel = color.pixel;
  971.  
  972.     color.red   = (unsigned short)     0;                            /* black */
  973.     color.green = (unsigned short)     0;
  974.     color.blue  = (unsigned short)     0;
  975.  
  976.     XAllocColor(theDisplay,theColormap,&color);
  977.     blackPixel = color.pixel;
  978.  
  979.     color.red   = (unsigned short) 40000;                        /* dark grey */
  980.     color.green = (unsigned short) 40000;
  981.     color.blue  = (unsigned short) 45000;
  982.  
  983.     XAllocColor(theDisplay,theColormap,&color);
  984.     darkGreyPixel = color.pixel;
  985.  
  986.     color.red   = (unsigned short) 48000;                      /* medium grey */
  987.     color.green = (unsigned short) 48000;
  988.     color.blue  = (unsigned short) 52000;
  989.  
  990.     XAllocColor(theDisplay,theColormap,&color);
  991.     mediumGreyPixel = color.pixel;
  992.  
  993.     color.red   = (unsigned short) 65535;                            /* white */
  994.     color.green = (unsigned short) 65535;
  995.     color.blue  = (unsigned short) 65535;
  996.  
  997.     XAllocColor(theDisplay,theColormap,&color);
  998.     whitePixel = color.pixel;
  999.  
  1000.     return;
  1001. }
  1002.  
  1003. /******************************************************************************/
  1004. /*                                                                            */
  1005. /* CalcGrid: calculates grid                                                  */
  1006. /*                                                                            */
  1007. /******************************************************************************/
  1008.  
  1009. void CalcGrid()
  1010.  
  1011. {
  1012.     double gridStepX, gridStepY;
  1013.     int    i, j, mapCenterX, mapCenterY;
  1014.  
  1015.     mapCenterX     = (int) (MARGINLFT + MAPWIDTH  / 2 - 1);
  1016.     mapCenterY     = (int) (MARGINTOP + MAPHEIGHT / 2 - 1);
  1017.  
  1018.     gridZero[0].x1 = mapCenterX;                             /* zero meridian */
  1019.     gridZero[0].x2 = mapCenterX;                 
  1020.     gridZero[0].y1 = (int) MARGINTOP;
  1021.     gridZero[0].y2 = (int) (MARGINTOP + MAPHEIGHT - 1);
  1022.     
  1023.     gridZero[1].x1 = (int) MARGINLFT;                              /* equator */
  1024.     gridZero[1].x2 = (int) (MARGINLFT + MAPWIDTH - 1);
  1025.     gridZero[1].y1 = mapCenterY;
  1026.     gridZero[1].y2 = mapCenterY;
  1027.     
  1028.     gridStepX      = GRIDSTEPX * GRIDSCALEX;
  1029.     gridStepY      = GRIDSTEPY * GRIDSCALEY;
  1030.  
  1031.     for (i = 0; i < NGRIDX; i++)                                  /* vertical */
  1032.     {
  1033.         j = 2 * i;
  1034.  
  1035.         gridLinesX[j].x1   = mapCenterX + (int) ((double) (i+1) * gridStepX);
  1036.         gridLinesX[j].x2   = mapCenterX + (int) ((double) (i+1) * gridStepX);
  1037.  
  1038.         gridLinesX[j+1].x1 = mapCenterX - (int) ((double) (i+1) * gridStepX);
  1039.         gridLinesX[j+1].x2 = mapCenterX - (int) ((double) (i+1) * gridStepX);
  1040.  
  1041.         gridLinesX[j].y1   = (int) MARGINTOP;
  1042.         gridLinesX[j].y2   = (int) (MARGINTOP + MAPHEIGHT - 1);
  1043.  
  1044.         gridLinesX[j+1].y1 = (int) MARGINTOP;
  1045.         gridLinesX[j+1].y2 = (int) (MARGINTOP + MAPHEIGHT - 1);
  1046.     }
  1047.  
  1048.     for (i = 0; i < NGRIDY; i++)                                /* horizontal */
  1049.     {
  1050.         j = 2 * i;
  1051.  
  1052.         gridLinesY[j].x1   = (int) MARGINLFT;
  1053.         gridLinesY[j].x2   = (int) (MARGINLFT + MAPWIDTH - 1);
  1054.  
  1055.         gridLinesY[j+1].x1 = (int) MARGINLFT;
  1056.         gridLinesY[j+1].x2 = (int) (MARGINLFT + MAPWIDTH - 1);
  1057.  
  1058.         gridLinesY[j].y1   = mapCenterY + (int) ((double) (i+1) * gridStepY);
  1059.         gridLinesY[j].y2   = mapCenterY + (int) ((double) (i+1) * gridStepY);
  1060.  
  1061.         gridLinesY[j+1].y1 = mapCenterY - (int) ((double) (i+1) * gridStepY);
  1062.         gridLinesY[j+1].y2 = mapCenterY - (int) ((double) (i+1) * gridStepY);
  1063.     }
  1064.  
  1065.     return;
  1066. }
  1067.  
  1068. /******************************************************************************/
  1069. /*                                                                            */
  1070. /* CalcMapLocation: calculates location of ground station, satellite and Sun  */
  1071. /*                                                                            */
  1072. /******************************************************************************/
  1073.  
  1074. void CalcMapLocation(mapLtd,mapLng,mapX,mapY)
  1075.  
  1076. double mapLtd, mapLng;
  1077. int    *mapX, *mapY;
  1078.  
  1079. {
  1080.     *mapX  = (int) ((MAPWIDTHD  / 2.0 - mapLng) * GRIDSCALEX - 0.5);
  1081.     *mapY  = (int) ((MAPHEIGHTD / 2.0 - mapLtd) * GRIDSCALEY - 0.5);
  1082.  
  1083.     *mapX += (int) MARGINLFT;
  1084.     *mapY += (int) MARGINTOP;
  1085.  
  1086.     return;
  1087. }
  1088.  
  1089. /******************************************************************************/
  1090. /*                                                                            */
  1091. /* CalcVisibCircle: calculates circle of visibility around sub-satellite      */
  1092. /*                  point, using an Euler matrix for the vector rotation      */
  1093. /*                                                                            */
  1094. /******************************************************************************/
  1095.  
  1096. void CalcVisibCircle(visibCirclePix,circLtd,circLng,circHgt,exHgt)
  1097.  
  1098. XSegment *visibCirclePix;
  1099. double   circLtd, circLng, circHgt, exHgt;
  1100.  
  1101. {
  1102.     double descMat[3][3], u[3], q[3];
  1103.     double arg, circStep, qabs;
  1104.     double the, psi, gamma, gammax, beta, lambda, lat, lng;
  1105.     double cosThe, sinThe, cosPsi, sinPsi;
  1106.     double cosBeta, sinBeta, cosLambda, sinLambda;
  1107.  
  1108.     int    i, k, posX, posY;
  1109.  
  1110.     the    = HALFPI - circLtd*CDR;
  1111.     psi    = HALFPI - circLng*CDR;
  1112.  
  1113.     cosThe = cos(the);
  1114.     sinThe = sin(the);
  1115.     cosPsi = cos(psi);
  1116.     sinPsi = sin(psi);
  1117.  
  1118.     descMat[0][0] =  sinPsi*cosThe;
  1119.     descMat[0][1] = -cosPsi;
  1120.     descMat[0][2] =  sinPsi*sinThe;
  1121.     descMat[1][0] =  cosPsi*cosThe;
  1122.     descMat[1][1] =  sinPsi;
  1123.     descMat[1][2] =  cosPsi*sinThe;
  1124.     descMat[2][0] = -sinThe;
  1125.     descMat[2][1] =  0.0;
  1126.     descMat[2][2] =  cosThe;
  1127.  
  1128.     arg  = EARTHRADIUS / (EARTHRADIUS + circHgt);
  1129.  
  1130.     if (arg >  1.0) arg =  1.0;
  1131.     if (arg < -1.0) arg = -1.0;
  1132.  
  1133.     gamma = acos(arg);
  1134.  
  1135.     if (exHgt > ONEPPM)                         /* for calculation of the ZOE */
  1136.     {
  1137.         arg = EARTHRADIUS / (EARTHRADIUS + exHgt);
  1138.  
  1139.         if (arg >  1.0) arg =  1.0;
  1140.         if (arg < -1.0) arg = -1.0;
  1141.  
  1142.         gammax = acos(arg);
  1143.         gamma += gammax;
  1144.     }
  1145.  
  1146.     beta     = HALFPI - gamma;
  1147.     cosBeta  = cos(beta);
  1148.     sinBeta  = sin(beta);
  1149.  
  1150.     circStep = 360.0 / ((double) NSEGSVC);
  1151.  
  1152.     for (k = 0; k < NSEGSVC;  k++)
  1153.     {
  1154.         lambda    = (double) (circStep * k) * CDR;
  1155.         cosLambda = cos(lambda);
  1156.         sinLambda = sin(lambda);
  1157.  
  1158.         u[0] = cosLambda*cosBeta;
  1159.         u[1] = sinLambda*cosBeta;
  1160.         u[2] = sinBeta;
  1161.  
  1162.         multMatVec(u,q,descMat);
  1163.  
  1164.         qabs  = absol(q);
  1165.  
  1166.         for (i = 0; i <= 2; i++)
  1167.             q[i] /= qabs;
  1168.  
  1169.         arg   = q[2];
  1170.  
  1171.         if (arg >  1.0) arg =  1.0;
  1172.         if (arg < -1.0) arg = -1.0;
  1173.  
  1174.         lat   = asin(arg) * CRD;
  1175.  
  1176.         q[2]  = 0.0;
  1177.         qabs  = absol(q);
  1178.  
  1179.         q[0] /= qabs;
  1180.         q[1] /= qabs;
  1181.  
  1182.         lng   = atan2(q[1],q[0]) * CRD;
  1183.         lng   = reduce(lng,-MAPWIDTHD/2.0,MAPWIDTHD/2.0);
  1184.  
  1185.         posX  = (int) ((MAPWIDTHD  / 2.0 - lng) * GRIDSCALEX + MARGINLFT - 0.5);
  1186.         posY  = (int) ((MAPHEIGHTD / 2.0 - lat) * GRIDSCALEY + MARGINTOP - 0.5);
  1187.  
  1188.         visibCirclePix[k].x1 = (short int) posX;
  1189.         visibCirclePix[k].y1 = (short int) posY;
  1190.  
  1191.         if (k > 0)
  1192.         {
  1193.             visibCirclePix[k-1].x2 = visibCirclePix[k].x1;
  1194.             visibCirclePix[k-1].y2 = visibCirclePix[k].y1;
  1195.         }
  1196.     }
  1197.  
  1198.     visibCirclePix[NSEGSVC-1].x2 = visibCirclePix[0].x1;      /* close circle */
  1199.     visibCirclePix[NSEGSVC-1].y2 = visibCirclePix[0].y1;
  1200.  
  1201.     CleanSegments(&visibCirclePix[0],NSEGSVC,TRUE);
  1202.  
  1203.     return;
  1204. }
  1205.  
  1206. /******************************************************************************/
  1207. /*                                                                            */
  1208. /* SaveGroundSegments: saves segments of visibility circle for all ground     */
  1209. /*                     stations                                               */
  1210. /*                                                                            */
  1211. /******************************************************************************/
  1212.  
  1213. void SaveGroundSegments(xSegments,num)
  1214.  
  1215. XSegment *xSegments;
  1216. int num;
  1217.  
  1218. {
  1219.     int i;
  1220.  
  1221.     for (i = 0; i < NSEGSVC; i++)
  1222.     {
  1223.         gndCircleSave[num].gndCircle[i].x1 = xSegments[i].x1;
  1224.         gndCircleSave[num].gndCircle[i].x2 = xSegments[i].x2;
  1225.         gndCircleSave[num].gndCircle[i].y1 = xSegments[i].y1;
  1226.         gndCircleSave[num].gndCircle[i].y2 = xSegments[i].y2;
  1227.     }
  1228.  
  1229.     return;
  1230. }
  1231.  
  1232. /******************************************************************************/
  1233. /*                                                                            */
  1234. /* LoadGroundSegments: loads segments of visibility circle for all ground     */
  1235. /*                     stations                                               */
  1236. /*                                                                            */
  1237. /******************************************************************************/
  1238.  
  1239. void LoadGroundSegments(xSegments,num)
  1240.  
  1241. XSegment *xSegments;
  1242. int num;
  1243.  
  1244. {
  1245.     int i;
  1246.  
  1247.     for (i = 0; i < NSEGSVC; i++)
  1248.     {
  1249.         xSegments[i].x1 = gndCircleSave[num].gndCircle[i].x1;
  1250.         xSegments[i].x2 = gndCircleSave[num].gndCircle[i].x2;
  1251.         xSegments[i].y1 = gndCircleSave[num].gndCircle[i].y1;
  1252.         xSegments[i].y2 = gndCircleSave[num].gndCircle[i].y2;
  1253.     }
  1254.  
  1255.     return;
  1256. }
  1257.  
  1258. /******************************************************************************/
  1259. /*                                                                            */
  1260. /* SaveTdrsSegments: saves segments of visibility circle for TDRS satellites  */
  1261. /*                                                                            */
  1262. /******************************************************************************/
  1263.  
  1264. void SaveTdrsSegments(xSegments,num)
  1265.  
  1266. XSegment *xSegments;
  1267. int num;
  1268.  
  1269. {
  1270.     int i;
  1271.  
  1272.     for (i = 0; i < NSEGSVC; i++)
  1273.     {
  1274.         tdrsCircleSave[num].tdrsCircle[i].x1 = xSegments[i].x1;
  1275.         tdrsCircleSave[num].tdrsCircle[i].x2 = xSegments[i].x2;
  1276.         tdrsCircleSave[num].tdrsCircle[i].y1 = xSegments[i].y1;
  1277.         tdrsCircleSave[num].tdrsCircle[i].y2 = xSegments[i].y2;
  1278.     }
  1279.  
  1280.     return;
  1281. }
  1282.  
  1283. /******************************************************************************/
  1284. /*                                                                            */
  1285. /* LoadTdrsSegments: loads segments of visibility circle for TDRS satellites  */
  1286. /*                                                                            */
  1287. /******************************************************************************/
  1288.  
  1289. void LoadTdrsSegments(xSegments,num)
  1290.  
  1291. XSegment *xSegments;
  1292. int num;
  1293.  
  1294. {
  1295.     int i;
  1296.  
  1297.     for (i = 0; i < NSEGSVC; i++)
  1298.     {
  1299.         xSegments[i].x1 = tdrsCircleSave[num].tdrsCircle[i].x1;
  1300.         xSegments[i].x2 = tdrsCircleSave[num].tdrsCircle[i].x2;
  1301.         xSegments[i].y1 = tdrsCircleSave[num].tdrsCircle[i].y1;
  1302.         xSegments[i].y2 = tdrsCircleSave[num].tdrsCircle[i].y2;
  1303.     }
  1304.  
  1305.     return;
  1306. }
  1307.  
  1308. /******************************************************************************/
  1309. /*                                                                            */
  1310. /* CalcGroundTrack: calculates ground track in pixels                         */
  1311. /*                                                                            */
  1312. /******************************************************************************/
  1313.  
  1314. void CalcGroundTrack()
  1315.  
  1316. {
  1317.     int  k, gndX, gndY;
  1318.  
  1319.     for (k = 0; k < NSEGSGT; k++)
  1320.     {
  1321.         gndX = (int) ((MAPWIDTHD/2.0  - groundTrack[k].lng) * GRIDSCALEX + 
  1322.                        MARGINLFT - 0.5);
  1323.  
  1324.         gndY = (int) ((MAPHEIGHTD/2.0 - groundTrack[k].ltd) * GRIDSCALEY + 
  1325.                        MARGINTOP - 0.5);
  1326.  
  1327.         groundTrackPix[k].x1 = (short int) gndX;
  1328.         groundTrackPix[k].y1 = (short int) gndY;
  1329.  
  1330.         if (k > 0)
  1331.         {
  1332.             groundTrackPix[k-1].x2 = groundTrackPix[k].x1;
  1333.             groundTrackPix[k-1].y2 = groundTrackPix[k].y1;
  1334.         }
  1335.     }
  1336.  
  1337.     groundTrackPix[NSEGSGT-1].x2 = groundTrackPix[NSEGSGT-1].x1;
  1338.     groundTrackPix[NSEGSGT-1].y2 = groundTrackPix[NSEGSGT-1].y1;
  1339.  
  1340.     CleanSegments(&groundTrackPix[0],NSEGSGT,FALSE);
  1341.  
  1342.     return;
  1343. }
  1344.  
  1345. /******************************************************************************/
  1346. /*                                                                            */
  1347. /* CleanSegments: cleans up line segments (wrap around at map boundaries)     */
  1348. /*                                                                            */
  1349. /******************************************************************************/
  1350.  
  1351. void CleanSegments(xSegments,numSegments,visibCircleFlag)
  1352.  
  1353. XSegment *xSegments;
  1354. int      numSegments, visibCircleFlag;
  1355.  
  1356. {
  1357.     int k, k0, n, dx, dy, dX, dY;
  1358.  
  1359.     k0 = (visibCircleFlag) ?  0 : -1;
  1360.  
  1361.     for (k = 0; k < numSegments + k0; k++)
  1362.     {
  1363.         n = (visibCircleFlag && k == numSegments - 1) ? 0 : k+1;
  1364.  
  1365.         if (xSegments[k].x1 - xSegments[k].x2 > (short int) (MAPWIDTH / 2))
  1366.         {
  1367.             dx = (int) (MAPWIDTH + MARGINLFT) - (int) xSegments[k].x1;
  1368.             dX = (int) xSegments[k].x2 - (int) MARGINLFT + dx;
  1369.  
  1370.             dY = (int) (xSegments[k].y2 - xSegments[k].y1);
  1371.  
  1372.             if (dX != 0)
  1373.                 dy = (int) ((double) dY / (double) dX * (double) dx);
  1374.             else
  1375.                 dy = 0;
  1376.  
  1377.             xSegments[n].x1 = xSegments[k].x2 - (short int) (dX - dx);
  1378.             xSegments[k].x2 = xSegments[k].x1 + (short int) dx;
  1379.  
  1380.             xSegments[n].y1 = xSegments[k].y2 - (short int) (dY - dy);
  1381.             xSegments[k].y2 = xSegments[k].y1 + (short int) dy;
  1382.         }
  1383.  
  1384.         if (xSegments[k].x2 - xSegments[k].x1 > (short int) (MAPWIDTH / 2))
  1385.         {
  1386.             dx = (int) xSegments[k].x1 - (int) MARGINLFT;
  1387.             dX = (int) (MAPWIDTH + MARGINLFT) - (int) xSegments[k].x2 + dx;
  1388.  
  1389.             dY = (int) (xSegments[k].y2 - xSegments[k].y1);
  1390.  
  1391.             if (dX != 0)
  1392.                 dy = (int) ((double) dY / (double) dX * (double) dx);
  1393.             else
  1394.                 dy = 0;
  1395.  
  1396.             xSegments[n].x1 = xSegments[k].x2 + (short int) (dX - dx);
  1397.             xSegments[k].x2 = xSegments[k].x1 - (short int) dx;
  1398.  
  1399.             xSegments[n].y1 = xSegments[k].y2 - (short int) (dY - dy);
  1400.             xSegments[k].y2 = xSegments[k].y1 + (short int) dy;
  1401.         }
  1402.     }
  1403.  
  1404.     for (k = 0; k < numSegments; k++)              /* clean up left and right */
  1405.     {
  1406.         if (xSegments[k].x1 < (short int) MARGINLFT)
  1407.             xSegments[k].x1 = (short int) MARGINLFT;
  1408.  
  1409.         if (xSegments[k].x2 < (short int) MARGINLFT)
  1410.             xSegments[k].x2 = (short int) MARGINLFT;
  1411.  
  1412.         if (xSegments[k].x1 > (short int) (MAPWIDTH + MARGINLFT - 1))
  1413.             xSegments[k].x1 = (short int) (MAPWIDTH + MARGINLFT - 1);
  1414.  
  1415.         if (xSegments[k].x2 > (short int) (MAPWIDTH + MARGINLFT - 1))
  1416.             xSegments[k].x2 = (short int) (MAPWIDTH + MARGINLFT - 1);
  1417.     }
  1418.  
  1419.     for (k = 0; k < numSegments; k++)              /* clean up top and bottom */
  1420.     {
  1421.         if (xSegments[k].y1 < (short int) MARGINTOP)
  1422.             xSegments[k].y1 = (short int) MARGINTOP;
  1423.  
  1424.         if (xSegments[k].y2 < (short int) MARGINTOP)
  1425.             xSegments[k].y2 = (short int) MARGINTOP;
  1426.  
  1427.         if (xSegments[k].y1 > (short int) (MAPHEIGHT + MARGINTOP - 1))
  1428.             xSegments[k].y1 = (short int) (MAPHEIGHT + MARGINTOP - 1);
  1429.  
  1430.         if (xSegments[k].y2 > (short int) (MAPHEIGHT + MARGINTOP - 1))
  1431.             xSegments[k].y2 = (short int) (MAPHEIGHT + MARGINTOP - 1);
  1432.     }
  1433.  
  1434.     return;
  1435. }
  1436.  
  1437. /******************************************************************************/
  1438. /*                                                                            */
  1439. /* main program                                                               */
  1440. /*                                                                            */
  1441. /******************************************************************************/
  1442.  
  1443. int StartGraphics()
  1444.  
  1445. {
  1446.     int n = 0;
  1447.  
  1448.     if (failFlag)
  1449.     {
  1450.         dispMessage("Attempt to open graphics window failed before.");
  1451.         return(FALSE);
  1452.     }
  1453.  
  1454.     initFlag = TRUE;
  1455.  
  1456.     if (firstGraphics)
  1457.     {
  1458.         lastSatGraphHeight = -2.0 * DHLIMIT;
  1459.         lastSunGraphTime   = ZERO;
  1460.         numGroundStations  = 1;
  1461.  
  1462.         argV[0] = "sattrack";
  1463.         argC    = 1;
  1464.  
  1465.         sprintf(appName,"%s",graphicsTitle);
  1466.  
  1467.         XtToolkitInitialize();
  1468.         appContext = XtCreateApplicationContext();
  1469.     }
  1470.  
  1471.     theDisplay = XtOpenDisplay(appContext,NULL,appName,appName,NULL,0,
  1472.                                &argC,argV);
  1473.  
  1474.     if (!theDisplay)
  1475.     {
  1476.         dispMessage("Attempt to open graphics window failed.");
  1477.         failFlag = TRUE;
  1478.         return(FALSE);
  1479.     }
  1480.  
  1481.     theScreen = DefaultScreen(theDisplay);
  1482.     topLevel  = XtAppCreateShell(appName,appName,
  1483.                     applicationShellWidgetClass,theDisplay,NULL,0);
  1484.  
  1485.     if (firstGraphics)
  1486.     {
  1487.         CreateColors();
  1488.         CalcGrid();
  1489.  
  1490.         mapSize = (MAPWIDTH > (unsigned int) 700) ? LARGE   : MEDIUM;
  1491.         mapSize = (MAPWIDTH > (unsigned int) 550) ? mapSize : SMALL;
  1492.  
  1493.         if (MAPTYPE == 1)                                         /* fill map */
  1494.         {
  1495.             foregroundPixel = greenPixel;
  1496.             backgroundPixel = oceanBluePixel;
  1497.         }
  1498.  
  1499.         else                                                      /* line map */
  1500.         {
  1501.             foregroundPixel = lightGreenPixel;
  1502.             backgroundPixel = nightBluePixel;
  1503.         }
  1504.  
  1505.         n = 0;
  1506.         XtSetArg(warg[n],XtNwidth,WINWIDTH); n++;
  1507.         XtSetArg(warg[n],XtNheight,WINHEIGHT); n++;
  1508.         XtSetArg(warg[n],XtNbackground,backgroundPixel); n++;
  1509.     }
  1510.  
  1511.     frame = XtCreateManagedWidget("frame",widgetClass,topLevel,warg,n);
  1512.  
  1513.     XtAppAddTimeOut(appContext,1L,TimeEvent,0);
  1514.  
  1515.     XtAddEventHandler(frame,StructureNotifyMask,FALSE,ResizeMap,NULL);
  1516.     XtAddEventHandler(frame,VisibilityChangeMask,FALSE,RedrawMap,NULL);
  1517.     XtAddEventHandler(frame,ExposureMask,FALSE,RedrawMap,NULL);
  1518.  
  1519.     XtRealizeWidget(topLevel);
  1520.  
  1521.     theWindow = XtWindow(topLevel);
  1522.     theGC     = XCreateGC(theDisplay,theWindow,0,0);
  1523.     drawable  = XtWindow(frame);
  1524.  
  1525.     pixmap    = XCreateBitmapFromData(theDisplay,(Drawable) drawable,
  1526.                     (char *) world_bits,MAPWIDTH,MAPHEIGHT);
  1527.  
  1528. /*
  1529.     XMoveWindow(theDisplay,theWindow,100,100);
  1530. */
  1531.  
  1532.     XMapRaised(theDisplay,(Drawable) drawable);
  1533.     XClearWindow(theDisplay,theWindow);
  1534.  
  1535.     UpdateGraphics(TRUE);                                  /* initial display */
  1536.  
  1537.     firstGraphics = FALSE;
  1538.     return(TRUE);
  1539. }
  1540.  
  1541. /******************************************************************************/
  1542. /*                                                                            */
  1543. /* RedrawMap: redraws map                                                     */
  1544. /*                                                                            */
  1545. /******************************************************************************/
  1546.  
  1547. void RedrawMap()
  1548.  
  1549. {
  1550.     DrawMap();
  1551.     return;
  1552. }
  1553.  
  1554. /******************************************************************************/
  1555. /*                                                                            */
  1556. /* ResizeMap: resizes map                                                     */
  1557. /*                                                                            */
  1558. /******************************************************************************/
  1559.  
  1560. void ResizeMap()
  1561.  
  1562. {
  1563.     DrawMap();
  1564.     return;
  1565. }
  1566.  
  1567. /******************************************************************************/
  1568. /*                                                                            */
  1569. /* TimeEvent: performs update of the map                                      */
  1570. /*                                                                            */
  1571. /******************************************************************************/
  1572.  
  1573. void TimeEvent(i,id)
  1574.  
  1575. int i;
  1576. XtIntervalId *id;
  1577.  
  1578. {
  1579.     DrawMap();
  1580.     return;
  1581. }
  1582.  
  1583. /******************************************************************************/
  1584. /*                                                                            */
  1585. /* CreateGraphicsTimeOut: sets graphics timer                                 */
  1586. /*                                                                            */
  1587. /******************************************************************************/
  1588.  
  1589. void CreateGraphicsTimeOut()
  1590.  
  1591. {
  1592.     XtAppAddTimeOut(appContext,1L,TimeEvent,0);
  1593.     return;
  1594. }
  1595.  
  1596. /******************************************************************************/
  1597. /*                                                                            */
  1598. /* UpdateGraphics: updates graphics display                                   */
  1599. /*                                                                            */
  1600. /******************************************************************************/
  1601.  
  1602. void UpdateGraphics(strtFlag)
  1603.  
  1604. int strtFlag;
  1605.  
  1606. {
  1607.     int  nEvents;
  1608.     char qStr[800], qqStr[800];
  1609.  
  1610.     lastMask = (unsigned long) 0;
  1611.     nEvents  = 0;
  1612.  
  1613.     if (strtFlag)
  1614.         milliSleep(100);
  1615.  
  1616.     sprintf(qStr,"X11 event queue (%d):",strtFlag);
  1617.  
  1618.     /* check the top of the event queue in order to find out */
  1619.     /* if an event is pending                                */
  1620.     /* the code within the 'while' loop is not optimized yet */
  1621.  
  1622.     while ((mask = XtAppPending(appContext)) != (unsigned long) 0)
  1623.     {
  1624.         strcpy(qqStr,qStr);
  1625.         sprintf(qStr,"%s %ld",qqStr,(long) mask);
  1626.  
  1627.         /* the next line gets the next event structure and dispatches */
  1628.         /* the event automatically already if it's a timer event      */
  1629.  
  1630.         XtAppNextEvent(appContext,&theEvent);
  1631.  
  1632.         /* if the event is an exposure or visibility change event and */
  1633.         /* it has not been dispatched yet, dispatch it now            */
  1634.  
  1635.         if (mask != lastMask && mask != (unsigned long) 2)
  1636.         {
  1637.             eventFlag = XtDispatchEvent(&theEvent);
  1638.             lastMask  = mask;
  1639.         }
  1640.  
  1641.         nEvents++;
  1642.     }
  1643.  
  1644.     if (nEvents > 0)
  1645.     {
  1646.         if (nEvents > 1)
  1647.         {
  1648.             strcpy(qqStr,qStr);
  1649.             sprintf(qStr,"%s (%d events)",qqStr,nEvents);
  1650.         }
  1651.  
  1652.         if (debugFlag)
  1653.             dispMessage(qStr);
  1654.     }
  1655.  
  1656.     return;
  1657. }
  1658.  
  1659. /******************************************************************************/
  1660. /*                                                                            */
  1661. /* QuitGraphics: quits graphics display                                       */
  1662. /*                                                                            */
  1663. /******************************************************************************/
  1664.  
  1665. void QuitGraphics()
  1666.  
  1667. {
  1668.     XFreePixmap(theDisplay,pixmap);
  1669.     XFreeGC(theDisplay,theGC);
  1670.     XDestroyWindow(theDisplay,theWindow);
  1671.     XCloseDisplay(theDisplay);
  1672.  
  1673.     return;
  1674. }
  1675.  
  1676. /******************************************************************************/
  1677. /*                                                                            */
  1678. /* dummy routines (these are used when SatTrack is compiled without X Window) */
  1679. /*                                                                            */
  1680. /******************************************************************************/
  1681.  
  1682. #else
  1683.  
  1684. int StartGraphics()
  1685. { return(99); }
  1686.  
  1687. void CreateGraphicsTimeOut()
  1688. { return; }
  1689.  
  1690. void UpdateGraphics(dummyI)
  1691. int dummyI;
  1692. { return; }
  1693.  
  1694. void QuitGraphics()
  1695. { return; }
  1696.  
  1697. #endif
  1698.  
  1699. /******************************************************************************/
  1700. /*                                                                            */
  1701. /* End of function block satgraph.c                                           */
  1702. /*                                                                            */
  1703. /******************************************************************************/
  1704.